package com.xingbg.projectimpl.provider.business.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author yuqi138
 * @version 1.0
 * @Description:一句话描述这个类的作用
 * @date 2021/5/27 20:29
 * @Copyright: 2021 www.jddglobal.com|www.haiyi-info.com Inc.All rights reserved.
 */
@Slf4j
public class ClassUtils {
    /**递归初始层级*/
    private static final Integer RECURSE_LEVEL_INIT = 0;
    /**递归最大层级*/
    private static final Integer RECURSE_LEVEL_MAX = 5;

    /**
     * 递归获取类上所有实现的接口(包含父类实现的接口)
     * @param clazz 待递归查询的类
     * @param allInterfaces 所有clazz实现接口集合
     * @param level 递归层级控制
     */
    public static void recurseAllInterfaces(Class clazz, Collection<Class> allInterfaces, int level){
        if(clazz==null || allInterfaces==null){
            return;
        }
        if(level > RECURSE_LEVEL_MAX){
            log.warn("递归层级超过上限["+RECURSE_LEVEL_MAX+"],禁止继续递归操作，防止栈内存溢出");
            return;
        }
        /**获取所有的申明接口*/
        Class[] declaredInterfaces = clazz.getInterfaces();
        if(declaredInterfaces!=null && declaredInterfaces.length>0){
            allInterfaces.addAll(Arrays.asList(declaredInterfaces));
        }
        /**获取父类上所有申明的接口*/
        Class superClass = clazz.getSuperclass();
        if(Object.class.getName().equalsIgnoreCase(superClass.getName())){
            return;
        }else{
            level++;
            recurseAllInterfaces(superClass,allInterfaces,level);
        }
    }

    /**
     * 获取某个类上所有实现接口申明的方法集合
     * @param clazz
     * @return
     */
    public static Collection<Method> getAllInterfaceMethods(Class clazz){
        List<Method> resultList = new ArrayList<>();
        if(clazz == null){
            return resultList;
        }
        /**获取该类上所有实现的接口*/
        Collection<Class> allInterfaces = new ArrayList<>();
        /**递归获取该类上所有实现的接口(包含父类实现接口)*/
        recurseAllInterfaces(clazz, allInterfaces, RECURSE_LEVEL_INIT);
        if(!CollectionUtils.isEmpty(allInterfaces)){
            for(Class interfaceClazz : allInterfaces){
                Method[] singleMethodList = interfaceClazz.getDeclaredMethods();
                if(singleMethodList!=null && singleMethodList.length>0){
//                    resultList.addAll(Arrays.stream(singleMethodList).map(Method::getName).collect(Collectors.toList()));
                    resultList.addAll(Arrays.asList(singleMethodList));
                }
            }
        }
        return resultList;
    }

    /**
     * 判断两个方法是否是覆盖关系
     * 方法名称是否相等 && 方法入参是否相等 && 方法出参是否相等
     * @param methodA
     * @param methodB
     * @return
     */
    public static boolean isOverrideMethod(Method methodA, Method methodB){
        return methodA.getName().equals(methodB.getName())
                && Arrays.equals(methodA.getParameterTypes(),methodB.getParameterTypes())
                && methodA.getReturnType().equals(methodB.getReturnType());
    }
}
